package src.com.server.service;

import src.com.qqcommon.Message;
import src.com.qqcommon.MessageType;
import src.com.qqcommon.User;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;

/**
 * 监听9990端口， 等待客户端连接，并保持通信
 */
public class QQServer {
    private ServerSocket ss = null;

    // 创建一个集合 存放多个用户 如果是集合内的用户登录 则认为是合法用户
    // 这里也可以使用线程安全的ConcurrentHashMap， HashMap是线程不安全的
    // 但在此处 只读HashMap 没有修改 所以HashMap也可以
    private static HashMap<String, User> validUsers = new HashMap<>();

    static { // 在静态代码块 初始化validUsers
        validUsers.put("100", new User("100", "123456"));
        validUsers.put("200", new User("200", "123456"));
        validUsers.put("300", new User("300", "123456"));
        validUsers.put("至尊宝", new User("至尊宝", "123456"));
        validUsers.put("紫霞仙子", new User("紫霞仙子", "123456"));
        validUsers.put("菩提老祖", new User("菩提老祖", "123456"));
    }

    // 验证登录用户是否合法
    public boolean checkUser(String userId, String pwd) {
        User user = validUsers.get(userId);
        if (user == null) { // 说明userID没有存在于validUsers中
            return false;
        }

        if (!user.getPassword().equals(pwd)) { // 密码不正确
            return false;
        }

        return true;
    }

    public QQServer() {
        // 注意端口 可以写在配置文件中
        try {
            System.out.println("服务端在9999端口监听......");
            // 启动推送新闻服务的线程
            new Thread(new SendNewsToAllService()).start();

            ss = new ServerSocket(9999);
            while (true) { // 当某个客户端建立连接后 或继续监听
                Socket socket = ss.accept();
                // 得到socket关联的对象输入流
                ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
                // 得到socket关联的对象输出流
                ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());

                User u = (User) ois.readObject(); // 读取客户端发送的User对象
                // 创建Message对象，准备回复客户端
                Message message = new Message();
                // 验证用户
                if (checkUser(u.getUserId(), u.getPassword())) { // 登录成功
                    message.setMesType(MessageType.MESSAGE_LOGIN_SUCCEED);
                    // 将Message对象回复给客户端
                    oos.writeObject(message);
                    // 创建一个线程 和客户端保持通信 该线程需要持有socket对象
                    ServerConnectClientThread serverConnectClientThread =
                            new ServerConnectClientThread(socket, u.getUserId());
                    // 启动该线程
                    serverConnectClientThread.start();
                    // 把该线程对象放入集合中进行管理
                    ManageClientThreads.addClientThread(u.getUserId(), serverConnectClientThread);
                } else { // 登录失败
                    System.out.println("用户 id=" + u.getUserId() + ",password=" + u.getPassword() + "验证失败！");
                    message.setMesType(MessageType.MESSAGE_LOGIN_FAIL);
                    oos.writeObject(message);
                    socket.close();
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally { // 如果服务端退出while 说明服务端不再监听 因此关闭ServerSocket
            try {
                assert ss != null;
                ss.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }


}
